package org.zuul.filter;

import com.google.common.collect.Maps;
import com.google.common.util.concurrent.RateLimiter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URL;
import java.util.Map;
import java.util.logging.Logger;

//@Component
public class RateLimitFilter extends ZuulFilter {

    private static Logger log = Logger.getLogger(RateLimitFilter.class.toString());
    private static RateLimiter rateLimiter = RateLimiter.create(1);

//(1) PRE：这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
//(2) ROUTING：这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求，并使用Apache HttpClient或Netfilx Ribbon请求微服务。
//(3) POST：这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
//(4) ERROR：在其他阶段发生错误时执行该过滤器。
    @Override
    public String filterType() {
       return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
// 这边的order一定要大于org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter的order
// 也就是要大于5
// 否则，RequestContext.getCurrentContext()里拿不到serviceId等数据。
        return Ordered.LOWEST_PRECEDENCE;
    }

    @Override
    public boolean shouldFilter() {
// 这里可以考虑弄个限流开启的开关，开启限流返回true，关闭限流返回false，你懂的。
        return true;
    }

    @Override
    public Object run() {
        try {
            RequestContext ctx = RequestContext.getCurrentContext();
            HttpServletRequest request = ctx.getRequest();
            log.info(request.getRequestURI());
            HttpServletResponse response = ctx.getResponse();
            if (!rateLimiter.tryAcquire()) {
//                HttpStatus httpStatus = HttpStatus.TOO_MANY_REQUESTS;
//                response.setContentType(MediaType.TEXT_PLAIN_VALUE);
//                response.setStatus(httpStatus.value());
//                response.getWriter().append(httpStatus.getReasonPhrase());
//                ctx.setSendZuulResponse(false);
//                throw new ZuulException(
//                        httpStatus.getReasonPhrase(),
//                        httpStatus.value(),
//                        httpStatus.getReasonPhrase()
//                );
                ctx.setSendZuulResponse(false);
                response.setStatus(200);
                response.getWriter().write("{\"code\": 99999,\"message\": \"too many requests.\"}");
            }
        } catch (Exception e) {
            log.warning(e.getMessage());
            ReflectionUtils.rethrowRuntimeException(e);
        }
        return null;
    }
}